﻿//#define NoOutput
using System;
using System.Collections.Generic;
using System.Drawing.Imaging;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Dynamic;

namespace ImageCompressor
{

    /// <summary>
    /// 一个单独的线程，来批量压缩图片
    /// </summary>
    class ImgsProcess
    {

        /// <summary>
        /// 这个压缩进程内的所有压缩图片的路径
        /// </summary>
        ImgPaths[] ImgPaths { get; set; }

        /// <summary>
        /// 计数当前线程编号，用于Debug
        /// </summary>
        public int threadIndex=-1;

        /// <summary>
        /// 引用的进度总控
        /// </summary>
        readonly CountProgress progress;

        int currentIndex = 0;

        /// <summary>
        /// 设定是否要在过程中停止计算，标记为停止后，等待计算停止
        /// </summary>
        public bool ToStop { get; set; } = false;

        /// <summary>
        /// 判断是否所有计算已经停止
        /// </summary>
        public bool Stoped { get; private set; } = false;
        /// <summary>
        /// 该线程处理的所有图片数量
        /// </summary>
        public int AllCount { get; private set; }

        public ImgsProcess(int index, List<ImgPaths> imgPaths, CountProgress countProgress)
        {
            threadIndex = index;
            ImgPaths = imgPaths.ToArray();
            AllCount = ImgPaths.Length;
            this.progress = countProgress;
        }
        /// <summary>
        /// 开始时设定所有的压缩参数
        /// </summary>
        /// <param name="compressLevel"></param>
        /// <param name="maxWidth"></param>
        /// <param name="maxHeight"></param>
        public void SetCompressLevel(int compressLevel,int maxWidth, int maxHeight)
        {
            this.compressLevel = compressLevel;
            this.maxWidth = maxWidth;
            this.maxHeight = maxHeight;
        }

        int compressLevel;
        int maxWidth;
        int maxHeight;

        /// <summary>
        /// 用来传递每个Img压缩时候的数据
        /// </summary>
        class DataPack
        {
            public DataPack(ImgPaths paths, JPGCompressor compressor)
            {
                this.compressor = compressor;
                this.imgPaths = paths; 
            }
            public JPGCompressor compressor;
            public ImgPaths imgPaths;
            public byte[] readBytes = null;
            public byte[] saveBytes = null;
        }
#if DEBUG

        double Tick => Math.Round(DateTime.Now.TimeOfDay.TotalSeconds % 1000, 3); 
#endif
        public void Start()
        {
            Stoped = false;
            ToStop = false;
            ResetCountData();
            while (currentIndex < AllCount)
            {
#if DEBUG
                long t1 = progress.stopwatch.ElapsedMilliseconds;
#endif
                DataPack dataPack = new DataPack(ImgPaths[currentIndex],new JPGCompressor(compressLevel,maxWidth,maxHeight));
                ReadOneImage(dataPack);
                CompressCurrent(dataPack);
                WriteOneImage(dataPack);
#if DEBUG
                long t2 = progress.stopwatch.ElapsedMilliseconds;
#endif
                progress.RWLock.AcquireWriterLock(-1);
                UpdateCountProgress();
                ResetCountData();
                Thread.Sleep(25);
                progress.RWLock.ReleaseWriterLock();
#if DEBUG

                Debug.WriteLine($"thread {threadIndex} count {currentIndex}, from {t1}, used {t2 - t1}");
#endif
                currentIndex++;
                if (ToStop)
                {
                    Stoped = true;
                    return;
                }
            }
            Stoped = true;
        }

        //当前线程运行的结果变量
        int successCount = 0;
        int failedCount = 0;
        List<string> failedPaths = new List<string>();
        int skipCount = 0;
        long preSizeKB = 0;
        long saveSizeKB = 0;

        /// <summary>
        /// 重置当前线程运行的结果变量
        /// </summary>
        void ResetCountData()
        {
            successCount = 0;
            failedCount = 0;
            failedPaths.Clear();
            skipCount = 0;
            preSizeKB = 0;
            saveSizeKB = 0;
        }
        /// <summary>
        /// 读照片到DataPack
        /// </summary>
        /// <param name="dataPack"></param>
        void ReadOneImage(DataPack dataPack)
        {
            ImgPaths imgPaths = dataPack.imgPaths;
            if(!imgPaths.ReadFileInfo.Exists)
            {
                failedCount++;
                failedPaths.Add(Localize.Get("Read file missing") + imgPaths.ReadFileInfo.FullName);
                return;
            }
            preSizeKB += imgPaths.ReadFileInfo.Length / 1024;
            if (FilesManager.IsSkip(imgPaths.ReadFileInfo))
            {
                skipCount++;
                return;
            }
            dataPack.readBytes = dataPack.compressor.ReadFileToBytes(imgPaths.ReadFileInfo, out string error);
            if (dataPack.readBytes == null)
            {
                failedCount++;
                failedPaths.Add(error + imgPaths.ReadFileInfo.FullName);
            }
        }

        /// <summary>
        /// 压缩得到文件的Bytes
        /// </summary>
        /// <param name="dataPack"></param>
        void CompressCurrent(DataPack dataPack)
        {
            if (dataPack.readBytes != null)
            {
                dataPack.saveBytes = dataPack.compressor.CompressBytes(dataPack.readBytes,out string error);
                if(dataPack.saveBytes == null)
                {
                    failedCount++;
                    failedPaths.Add(error + dataPack.imgPaths.ReadFileInfo.FullName);
                }
            }
        }


        bool DeleteOriginalImage(ImgPaths imgPaths,out string error)
        {
            error = null;
            if (!imgPaths.KeepOriginal)
            {
                
                try
                {
                    imgPaths.ReadFileInfo.Delete();
                    
                }
                catch 
                {
                    error = Localize.Get("Cannot delete original image:  ")+imgPaths.ReadFileInfo.FullName;
                    return false;
                }

            }
            return true;
        }

        /// <summary>
        /// 写Bytes到文件
        /// </summary>
        /// <param name="dataPack"></param>
        void WriteOneImage(DataPack dataPack)
        {
            if (dataPack.saveBytes != null)
            {
                bool re = dataPack.compressor.SaveCompressBytes(dataPack.saveBytes, dataPack.imgPaths.SaveFileInfo, out string error);
                if (re)
                {
                    saveSizeKB += dataPack.saveBytes.LongLength / 1024;
                    successCount++;
                }
                else
                {
                    failedCount++;
                    failedPaths.Add(error + dataPack.imgPaths.SaveFileInfo.FullName);
                }
                if(!DeleteOriginalImage(dataPack.imgPaths, out string error2))
                {
                    failedPaths.Add(error2);
                }

            }
        }

        /// <summary>
        /// 将本线程结果更新到progress的结果
        /// </summary>
        void UpdateCountProgress()
        {
            if (progress.Finished) return;
            progress.SuccessCount += successCount;
            progress.FailedCount+= failedCount;
            progress.SkipCount += skipCount;
            progress.FailedInfos.AddRange(failedPaths);
            progress.PreSizeKBSum+= preSizeKB;
            progress.PostSizeKBSum += saveSizeKB;
            progress.Update();
        }


    }
}
